package com.example.backend.condition;


import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisConnectionException;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.sync.RedisCommands;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

import java.time.Duration;

@Slf4j
public class OnRedisAvailableCondition implements Condition {

    private static final String PONG_RESPONSE = "PONG";
    // 缓存结果
    private static volatile Boolean redisAvailableCache;
    // 记录上次检查的host
    private static String lastHost;
    // 记录上次检查的port
    private static Integer lastPort;

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String host = context.getEnvironment().getProperty("spring.redis.host");
        String portStr = context.getEnvironment().getProperty("spring.redis.port");

        if (host == null || portStr == null) {
            log.warn("Redis 配置错误: 缺少配置信息");
            return false;
        }

        int port;
        try {
            port = Integer.parseInt(portStr);
        } catch (NumberFormatException e) {
            log.warn("Redis 配置错误: 端口号格式不正确");
            return false;
        }

        // 配置未变化且缓存存在时直接返回缓存结果
        if (redisAvailableCache != null && host.equals(lastHost) && port == lastPort) {
            return redisAvailableCache;
        }

        // 双重检查锁
        synchronized (OnRedisAvailableCondition.class) {
            if (redisAvailableCache != null && host.equals(lastHost) && port == lastPort) {
                return redisAvailableCache;
            }

            boolean result = checkRedisAvailable(host, port);
            redisAvailableCache = result;
            lastHost = host;
            lastPort = port;
            return result;
        }
    }

    private boolean checkRedisAvailable(String host, int port) {
        RedisClient redisClient = null;
        try {
            RedisURI redisUri = RedisURI.Builder.redis(host, port)
                    .withTimeout(Duration.ofSeconds(5))
                    .build();
            redisClient = RedisClient.create(redisUri);

            try (StatefulRedisConnection<String, String> connection = redisClient.connect()) {
                RedisCommands<String, String> commands = connection.sync();
                String response = commands.ping();
                log.debug("Redis 连接成功, host: {}, port: {}, PING 响应: {}", host, port, response);
                return PONG_RESPONSE.equalsIgnoreCase(response);
            }
        } catch (RedisConnectionException e) {
            log.warn("Redis 连接失败, host: {}, port: {}: {}", host, port, e.getMessage());
            return false;
        } catch (Exception e) {
            log.warn("Redis 操作异常, host: {}, port: {}: {}", host, port, e.getMessage());
            return false;
        } finally {
            if (redisClient != null) {
                log.debug("Redis 释放连接");
                redisClient.shutdown();
            }
        }
    }
}